---
title: 按需渲染适配器
i18nReady: true
---
import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro';
import RecipeLinks from '~/components/RecipeLinks.astro';
import IntegrationsNav from '~/components/IntegrationsNav.astro'

Astro 允许你为部分或所有页面和端点选择**按需渲染**。这也被称为**服务器端渲染 (SSR)**：在服务器上根据请求生成 HTML 页面，并将其发送给客户端。一个**适配器**被用来在服务器上运行你的项目并处理这些请求。

这种按需渲染允许你：

- 在应用中实现登录状态的会话。
- 从使用 `fetch()` 动态调用的 API 呈现数据。
- 使用 *适配器* 将站点部署到主机。

如果你需要以下功能，可以考虑在你的 Astro 项目中启用按需服务器渲染：

- **API 端点**：创建作为 API 端点的特定页面，用于数据库访问、身份验证和授权等任务，同时将敏感数据隐藏在服务端。

- **受保护的页面**：通过在服务器上处理用户访问，以限制对页面的访问。

- **频繁更改的内容**：生成单个页面时无需静态重建你的网站。当页面的内容频繁更新时，这是非常有用的，例如动态调用 `fetch()` 从 API 获取的数据。


## 官方适配器

Astro 为 [Node.js](https://nodejs.org/)、[Vercel](https://vercel.com/)、[Netlify](https://www.netlify.com/) 和 [Cloudflare](https://www.cloudflare.com/) 维护了官方的适配器。

在我们的集成目录中，你也可以找到更多[社区维护的适配器](https://astro.build/integrations/?search=&categories%5B%5D=adapters)（例如 Deno、SST、AWS）。

<IntegrationsNav category="adapter"/>

## 启用按需服务器渲染

Astro 的两种按需渲染输出模式（`server` 和 `hybrid`）都允许你通过尽可能预渲染单个路由来利用静态站点的性能优势，不论你是拥有一个完全动态的应用，还是大部分都是静态的网站，只需要为选定的路由进行按需渲染。

为了决定在你的项目中使用哪一个，请选择一个 `output` 选项，这个选项代表了你的**大部分**页面和路由将如何被渲染：

- __`output: 'server'`__：默认按需渲染。当你的网站或应用的大部分或全部应该在请求时进行服务器渲染时使用这个选项。任何单独的页面或端点都可以*选择加入*预渲染。
- __`output: 'hybrid'`__：默认预渲染为 HTML。在你的网站大部分应该是静态的时候使用这个选项。任何单独的页面或端点都可以*选择退出*预渲染。
 
因为服务器需要按需生成至少一些页面，所以这两种模式都需要你[添加一个适配器](#添加一个适配器)来执行服务器功能。

### 添加一个适配器

要在 `server` 或 `hybrid` 模式下部署项目，你需要添加一个**适配器**。这是因为这两种模式都需要一个服务器 _运行时_：在服务器上运行代码以在请求时生成页面的环境。每个适配器都允许 Astro 输出一个在特定运行时（如 Vercel、Netlify 或 Cloudflare）上运行你的项目的脚本。

你可以在我们的 [集成目录](https://astro.build/integrations/?search=&categories%5B%5D=adapters) 中找到官方和社区的适配器。然后选择与你的 [部署环境](/zh-cn/guides/deploy/) 相对应的适配器。

#### 使用 `astro add` 安装

你可以使用以下 `astro add` 命令添加任何 [由 Astro 维护的官方适配器](/zh-cn/guides/integrations-guide/)。这将会一步到位地完成适配器的安装，并对 `astro.config.mjs` 文件进行适当的修改。例如，要安装 Vercel 适配器，请运行：

<PackageManagerTabs>
  <Fragment slot="npm">
  ```shell
  npx astro add vercel
  ```
  </Fragment>
  <Fragment slot="pnpm">
  ```shell
  pnpm astro add vercel
  ```
  </Fragment>
  <Fragment slot="yarn">
  ```shell
  yarn astro add vercel
  ```
  </Fragment>
</PackageManagerTabs>

#### 手动安装

你也可以通过手动安装包并更新 `astro.config.mjs` 自己添加适配器。例如，要手动安装 Vercel 适配器：

1. 使用你首选的包管理器将适配器安装到你的项目依赖项：

   <PackageManagerTabs>
     <Fragment slot="npm">
     ```shell
     npm install @astrojs/vercel
     ```
     </Fragment>
     <Fragment slot="pnpm">
     ```shell
     pnpm add @astrojs/vercel
     ```
     </Fragment>
     <Fragment slot="yarn">
     ```shell
     yarn add @astrojs/vercel
     ```
     </Fragment>
   </PackageManagerTabs>

2. [添加一个适配器](/zh-cn/reference/configuration-reference/#adapter)到你的 `astro.config.mjs` 文件的导入和默认导出，以及你想要的 `output` 模式：

    ```js ins={3,7} {6}
    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    import vercel from '@astrojs/vercel/serverless';

    export default defineConfig({
      output: 'server',
      adapter: vercel(),
    });
    ```

    注意，不同的适配器可能也有不同的配置设置。请阅读每个适配器的文档，并将任何必要的配置选项应用到 `astro.config.mjs` 中你选择的适配器。


### 配置 `sever` 或 `hybrid` 模式

要启用按需渲染，必须将你的 `output` 配置为两种服务器渲染模式之一。

例如，要配置一个高度动态的应用，其中每个页面默认都由服务器按需渲染，将 `output: 'server'` 添加到你的 Astro 配置中：

```js ins={5} title="astro.config.mjs"
import { defineConfig } from 'astro/config';
import node from "@astrojs/node";

export default defineConfig({
  output: 'server',
  adapter: node({
    mode: "standalone"
  })
});
```

### 在 `server` 模式中选择加入预渲染

对于大部分以 `output: server` 配置的服务器渲染应用，添加 `export const prerender = true` 到任何页面或路由，以预渲染一个静态页面或端点：

```astro title="src/pages/mypage.astro" {2}
---
export const prerender = true;
// ...
---
<html>
  <!-- 这里是静态的、预渲染的页面... -->
</html>
```

```mdx title="src/pages/mypage.mdx" {5}
---
layout: '../layouts/markdown.astro'
title: 'My page'
---
export const prerender = true;

# 这是我的静态的、预渲染的页面
```

```js title="src/pages/myendpoint.js" {1}
export const prerender = true;

export async function GET() {
  return new Response(
    JSON.stringify({
      message: `这是我的静态端点`,
    }),
  );
}
```

### 在 `hybrid` 模式中选择退出预渲染

对于大部分以 `output: hybrid` 配置的静态网站，添加 `export const prerender = false` 到任何应该按需服务器渲染的文件：

```js title="src/pages/randomnumber.js" {1}
export const prerender = false;

export async function GET() {
  let number = Math.random();
  return new Response(
    JSON.stringify({
      number,
      message: `这是一个随机数：${number}`,
    }),
  );
}
```

## 按需渲染功能特性

### HTML 流式处理

在 HTML 流式传输中，一个文档会被分割成多个块，然后按顺序通过网络发送，并按该顺序在页面上渲染。在 `server` 或 `hybrid` 模式下，Astro 使用 HTML 流式传输将每个组件在渲染时发送到浏览器。尽管网络条件可能导致大文档下载缓慢，等待数据获取可能会阻塞页面渲染，但这确保用户能尽快地看到你的 HTML。

<RecipeLinks slugs={["zh-cn/recipes/streaming-improve-page-performance"]} />

:::caution
修改 [响应头](https://developer.mozilla.org/zh-CN/docs/Glossary/Response_header) 的功能只在**页面级别**可用。（你不能在组件内部使用它们，包括布局组件。）当 Astro 运行你的组件代码时，它已经发送了响应头，无法进行修改。

:::

### Cookies

这是一个用于读取和修改单个 cookie 的工具方法。它允许你检查、设置、获取和删除 cookie。

下面的示例更新了页面显示的计数器的 cookie 值。

```astro title="src/pages/index.astro" {4,5,9}
---
let counter = 0

if (Astro.cookies.has("counter")) {
  const cookie = Astro.cookies.get("counter")
	counter = cookie.number() + 1
}

Astro.cookies.set("counter",counter)
---
<html>
  <h1>Counter = {counter}</h1>
</html>
```

在 API 参考中查看有关 [`Astro.cookies` 和 `AstroCookie` 类型](/zh-cn/reference/api-reference/#astrocookies) 的更多详细信息。

### `Response`

你也可以从使用按需渲染的任何页面返回一个 [响应](https://developer.mozilla.org/zh-CN/docs/Web/API/Response)。

下面的例子在数据库中查找 id 后在动态页面上返回 404：

```astro title="src/pages/[id].astro" {8-11}
---
import { getProduct } from '../api';

const product = await getProduct(Astro.params.id);

// 没有找到任何记录
if(!product) {
  return new Response(null, {
    status: 404,
    statusText: 'Not found'
  });
}
---
<html>
  <!-- 你的页面 -->
</html>
```

### `Request`

`Astro.request` 是一个标准的 [请求](https://developer.mozilla.org/zh-CN/docs/Web/API/Request) 对象。它可以用来获取请求的 `url`、`headers`、`method`，甚至是请求的主体。

在 `server` 和 `hybrid` 模式下，对于非静态生成的页面，你可以从这个对象中获取更多信息。


### `Astro.request.headers`

请求的标头可在 `Astro.request.headers` 上找到。这就像浏览器的 [`Request.headers`](https://developer.mozilla.org/zh-CN/docs/Web/API/Request/headers)。它是一个 [标头](https://developer.mozilla.org/zh-CN/docs/Web/API/Headers) 对象，你可以在其中检索标头，例如 cookie。

```astro title="src/pages/index.astro" {2}
---
const cookie = Astro.request.headers.get('cookie');
// ...
---
<html>
  <!-- 你的页面 -->
</html>
```

### `Astro.request.method`

请求中使用的 HTTP 方法可用作 `Astro.request.method`。这就像浏览器的 [`Request.method`](https://developer.mozilla.org/zh-CN/docs/Web/API/Request/method) 一样。它返回请求中使用的 HTTP 方法的字符串表示形式。

```astro title="src/pages/index.astro"
---
console.log(Astro.request.method) // GET (在浏览器中导航到时)
---
```

在 API 参考中查看有关 [`Astro.request`](/zh-cn/reference/api-reference/#astrorequest) 的更多详细信息。

### 服务器端点

服务器端点，也称为 **API 路由**，是从 `src/pages/` 文件夹中的 `.js`或 `.ts` 文件导出的特殊函数。按需服务器端渲染的一个强大特性是，API 路由能够在服务器上安全地执行代码。


该函数接收一个[端点上下文对象](/zh-cn/reference/api-reference/#端点上下文)并返回一个 [Response](https://developer.mozilla.org/zh-CN/docs/Web/API/Response)。

要了解更多信息，请参阅我们的[端点指南](/zh-cn/guides/endpoints/#服务器端点api-路由)。
